/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <string.h>
#include "wifi/wifi_hotspot.h"
#include "wifi_hotspot_config.h"
#include "station_info.h"
#include "wifi_error_code.h"
#include "wifi_hotspot_config.h"
#include "lwip/ip4_addr.h"

#define RSSI_LEVEL_4_2_G (-65)
#define RSSI_LEVEL_3_2_G (-75)
#define RSSI_LEVEL_2_2_G (-82)
#define RSSI_LEVEL_1_2_G (-88)
#define RSSI_LEVEL_4_5_G (-65)
#define RSSI_LEVEL_3_5_G (-72)
#define RSSI_LEVEL_2_5_G (-79)
#define RSSI_LEVEL_1_5_G (-85)

static HotspotConfig g_wifiApConfig = {0};

static WifiErrorCode WifiIsWifiInited(void)
{
    /* 等待wifi初始化完成 */
    while (wifi_is_wifi_inited() == 0) {
        (void)osDelay(10); /* 1: 等待100ms后判断状态 */
    }
    return 0;
}

WifiErrorCode EnableHotspot(void)
{
    (void)WifiIsWifiInited();
    if (LockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    softap_config_stru hapd_conf = {0};
    softap_config_advance_stru config = {0};
    char ifname[WIFI_IFNAME_MAX_SIZE + 1] = "ap0"; /* 创建的SoftAp接口名 */
    struct netif *netif_p = NULL;
    ip4_addr_t   st_gw;
    ip4_addr_t   st_ipaddr;
    ip4_addr_t   st_netmask;
    IP4_ADDR(&st_ipaddr, 192, 168, 43, 1); /* IP地址设置：192.168.43.1 */
    IP4_ADDR(&st_netmask, 255, 255, 255, 0); /* 子网掩码设置：255.255.255.0 */
    IP4_ADDR(&st_gw, 192, 168, 43, 2); /* 网关地址设置：192.168.43.2 */

    printf("SoftAP try enable.\r\n");

    memcpy_s(hapd_conf.ssid, sizeof(hapd_conf.ssid), g_wifiApConfig.ssid, sizeof(g_wifiApConfig.ssid));
    memcpy_s(hapd_conf.pre_shared_key, WIFI_MAX_KEY_LEN, g_wifiApConfig.preSharedKey, WIFI_MAX_KEY_LEN);
    hapd_conf.security_type = HoSecToHiSec(g_wifiApConfig.securityType);
    hapd_conf.channel_num = g_wifiApConfig.channelNum;
    hapd_conf.wifi_psk_type = 0;

    /* 配置SoftAp网络参数 */
    config.beacon_interval = 100; /* 100：Beacon周期设置为100ms */
    config.dtim_period = 2; /* 2：DTIM周期设置为2 */
    config.gi = 0; /* 0：short GI默认关闭 */
    config.group_rekey = 86400; /* 86400：组播秘钥更新时间设置为1天 */
    config.protocol_mode = 4; /* 4：协议类型设置为802.11b + 802.11g + 802.11n + 802.11ax */
    config.hidden_ssid_flag = 1; /* 1：不隐藏SSID */
    if (wifi_set_softap_config_advance(&config) != 0) {
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    /* 启动SoftAp接口 */
    if (wifi_softap_enable(&hapd_conf) != 0) {
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    /* 配置DHCP服务器 */
    netif_p = netif_find(ifname);
    if (netif_p == NULL) {
        (void)wifi_softap_disable();
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    if (netifapi_netif_set_addr(netif_p, &st_ipaddr, &st_netmask, &st_gw) != 0) {
        (void)wifi_softap_disable();
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    if (netifapi_dhcps_start(netif_p, NULL, 0) != 0) {
        (void)wifi_softap_disable();
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    printf("SoftAp start success.\r\n");
    return WIFI_SUCCESS;

}

WifiErrorCode DisableHotspot(void)
{
    wifi_softap_disable();
}

WifiErrorCode SetHotspotConfig(const HotspotConfig *config)
{
    if (LockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    int ret = memcpy_s(&g_wifiApConfig, sizeof(HotspotConfig), config, sizeof(HotspotConfig));
    if (ret != 0) {
        printf("[wifi_service]:SetHotspotConfig memcpy fail, err = %d\n", ret);
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    return WIFI_SUCCESS;

}

WifiErrorCode GetHotspotConfig(HotspotConfig *result)
{
    if (LockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    int ret = memcpy_s(&g_wifiApConfig, sizeof(HotspotConfig), result, sizeof(HotspotConfig));
    if (ret != 0) {
        printf("[wifi_service]:GetHotspotConfig memcpy fail, err = %d\n", ret);
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    return WIFI_SUCCESS;
}

int IsHotspotActive(void)
{
    return wifi_is_softap_enabled();
}

WifiErrorCode GetStationList(StationInfo *result, unsigned int *size)
{
    wifi_sta_info_stru *wifi_sta_list = {0};
    int staNum = 0;
    int ret = wifi_softap_get_sta_list(&wifi_sta_list, staNum);
    if (ret != WIFI_SUCCESS) {
        printf("[wifi_service]:GetStationList fail, err =  %d\r\n", ret);
        return ERROR_WIFI_NOT_AVAILABLE;
    }
    size = staNum;
    memcpy_s(result, (sizeof(result[0]) * staNum), 0, sizeof(result[0]) * staNum);
    for (unsigned int i = 0; i < staNum; i++) {
        memcpy_s(result[i].macAddress, sizeof(result[i].macAddress),
                 wifi_sta_list[i].mac_addr, sizeof(wifi_sta_list[i].mac_addr));
    }
    return WIFI_SUCCESS;

}

WifiErrorCode DisassociateSta(unsigned char *mac, int macLen)
{
    int ret = wifi_softap_deauth_sta(mac, macLen);
    if (ret != 0) {
        printf("[wifi_service]:DisassociateSta fail, err = %d\n", ret);
        return ERROR_WIFI_UNKNOWN;
    }
    return WIFI_SUCCESS;
}

WifiErrorCode AddTxPowerInfo(int power)
{
    return;
}


WifiErrorCode SetBand(int band)
{
    if (band != HOTSPOT_BAND_TYPE_2G) {
        return ERROR_WIFI_NOT_SUPPORTED;
    }
    if (LockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    g_wifiApConfig.band = band;
    if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    return WIFI_SUCCESS;
}

WifiErrorCode GetBand(int *result)
{
    if (result == NULL) {
        return ERROR_WIFI_INVALID_ARGS;
    }

    if (LockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    if (g_wifiApConfig.band == 0) {
        if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_NOT_AVAILABLE;
    }
    if (UnlockWifiGlobalLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
    *result = HOTSPOT_BAND_TYPE_2G;
    return WIFI_SUCCESS;
}


int GetSignalLevel(int rssi, int band)
{
    if (band == HOTSPOT_BAND_TYPE_2G) {
        if (rssi >= RSSI_LEVEL_4_2_G)
            return RSSI_LEVEL_4;
        if (rssi >= RSSI_LEVEL_3_2_G)
            return RSSI_LEVEL_3;
        if (rssi >= RSSI_LEVEL_2_2_G)
            return RSSI_LEVEL_2;
        if (rssi >= RSSI_LEVEL_1_2_G)
            return RSSI_LEVEL_1;
    }

    if (band == HOTSPOT_BAND_TYPE_5G) {
        if (rssi >= RSSI_LEVEL_4_5_G)
            return RSSI_LEVEL_4;
        if (rssi >= RSSI_LEVEL_3_5_G)
            return RSSI_LEVEL_3;
        if (rssi >= RSSI_LEVEL_2_5_G)
            return RSSI_LEVEL_2;
        if (rssi >= RSSI_LEVEL_1_5_G)
            return RSSI_LEVEL_1;
    }
    return ERROR_WIFI_INVALID_ARGS;
}
